package com.aynu.stack;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

/**
 * @author mj
 * @version 1.0
 * @date 2020/12/14 14:46
 * 用stack综合计算器实现计算器
 * <p>
 * 中缀表达式()
 */
public class Calculator {
    public static void main(String[] args) {
        //计算的运算符
        String str = "70*7*1-5+3-4";
        //定义两个栈
        ArrayStack2 numStack = new ArrayStack2(10);//数字栈
        ArrayStack2 operStack = new ArrayStack2(10);//运算符栈
        //定义指针
        int index = 0;
        int num1;    //第一个数
        int num2;    //第二个数
        int chr;     //记录栈顶运算符
        int result = 0;  //结果集
        String keepNum = "";
        //循环入栈
        while (true) {
            //截取字符串
            int c = str.substring(index, index + 1).charAt(0);
            //判断是否是运算符
            if (operStack.isOperator(c)) {
                //判断运算符栈是否为空
                if (!operStack.isEmpty()) {
                    //判断当前运算符的优先级是否比运算符栈的运算符高
                    if (operStack.priority(c) <= operStack.getTop()) {
                        chr = operStack.pop();
                        num1 = numStack.pop();
                        num2 = numStack.pop();
                        result = numStack.arithmetic(num1, num2, chr);
                        //数组入栈
                        numStack.put(result);
                        ///运算符入栈
                        operStack.put(c);
                    } else {
                        operStack.put(c);
                    }
                } else {
                    operStack.put(c);
                }
            } else {
                //不能直接入栈，需要考虑到多为数字
                char d = (char) c;
                keepNum += d;
                //判断是否是最后一个字符
                if (index == str.length() - 1) {
                    numStack.put(Integer.parseInt(keepNum));
                } else {
                    //判断下一个的字符是否是运算符
                    if (operStack.isOperator(str.substring(index + 1, index + 2).charAt(0))) {
                        numStack.put(Integer.parseInt(keepNum));
                        //清空ch
                        keepNum = "";
                    }
                }
                //numStack.put(c-48);
            }

            //结束循环的条件，到字符串末尾结束循环
            index++;
            if (index == str.length()) {
                break;
            }
        }

        //计算
        while (true) {
            //当operStack为空时，结束循环
            if (operStack.top == -1) {
                break;
            }
            //计算结果
            num1 = numStack.pop();
            num2 = numStack.pop();
            chr = operStack.pop();
            result = numStack.arithmetic(num1, num2, chr);
            //数组入栈
            numStack.put(result);
        }

        //打印结果
        System.out.printf("%s = %d", str, result);
    }
}

class ArrayStack2 {
    public int maxSize;   //数组的大小
    public int[] stack;   //定义一个栈
    public int top = -1;  //表示栈顶，-1表示没有数据

    //构造方法
    public ArrayStack2(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[maxSize];
    }

    //栈满判断
    public boolean isMan() {
        return this.top == maxSize - 1;
    }

    //栈空判断
    public boolean isEmpty() {
        return top == -1;
    }

    //入栈
    public void put(int num) {
        if (isMan()) {
            System.out.println("栈满");
            return;
        }
        top++;
        stack[top] = num;
    }

    //获取top的数据
    public int getTop() {
        return stack[top];
    }

    //出栈
    public int pop() {
        if (isEmpty()) {
            throw new RuntimeException("栈为空");
        }
        int value = stack[top];
        top--;
        return value;
    }

    //遍历栈
    public void list() {
        if (isEmpty()) {
            System.out.println("栈为空");
            return;
        }
        for (int i : stack) {
            System.out.println(i);
        }
    }

    //表达式的优先级判断,程序员自己设定
    public int priority(int oper) {
        if (oper == '*' || oper == '/') {
            return 1;
        } else if (oper == '+' || oper == '-') {
            return 0;
        } else {
            throw new RuntimeException("非法运算符");
        }
    }

    //判断是否是一个运算符
    public boolean isOperator(int oper) {
        return oper == '*' || oper == '/' || oper == '+' || oper == '-';
    }

    //进行计算
    public int arithmetic(int num1, int num2, int oper) {
        int res = 0;
        switch (oper) {
            case '*':
                res = num1 * num2;
                break;
            case '/':
                res = num2 / num1;
                break;
            case '+':
                res = num1 + num2;
                break;
            case '-':
                res = num2 - num1;
                break;
            default:
                throw new RuntimeException();
        }
        return res;
    }
}